package com.joysuch.wwyt.alert.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.gson.reflect.TypeToken;
import com.joysuch.wwyt.alert.enums.GeTuiChannelLevelEnum;
import com.joysuch.wwyt.alert.enums.GeTuiClickTypeEnum;
import com.joysuch.wwyt.alert.request.*;
import com.joysuch.wwyt.alert.result.GeTuiResult;
import com.joysuch.wwyt.alert.result.response.GeTuiAuthResponse;
import com.joysuch.wwyt.alert.service.AlertMessageService;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.common.util.JsonUtil;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseLoginAccount;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiCoreException;
import com.joysuch.wwyt.core.repository.BaseLoginAccountDao;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.log.entity.MessagePushLog;
import com.joysuch.wwyt.log.service.MessagePushLogService;
import com.joysuch.wwyt.util.GsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class AlertMessageServiceImpl implements AlertMessageService {

    @Autowired
    private MessagePushLogService messagePushLogService;

    @Autowired
    private BaseConfigService baseConfigService;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private BaseLoginAccountDao loginAccountDao;

    @Override
    public String getTokenFromCache() throws ApiCoreException {
        String redisKey = BaseConfigCodes.GETUI_TOKEN_REDIS_KEY;
        String token = redisClient.get(redisKey);
        if (StringUtils.isNotEmpty(token)) {
            return token;
        } else {
            GeTuiAuthResponse response = getGeTuiToken();
            if (response != null) {
                token = response.getToken();
                redisClient.setEx(redisKey, token, 20, TimeUnit.HOURS);
                return token;
            }
        }
        return null;
    }

    public GeTuiAuthResponse getGeTuiToken() throws ApiCoreException {
        BaseConfig appKeyConfig = baseConfigService.findFirstConfig(BaseConfigCodes.GETUI_APP_KEY);
        BaseConfig masterSecretConfig = baseConfigService.findFirstConfig(BaseConfigCodes.GETUI_MASTER_SECRET);
        BaseConfig httpUrlConfig = baseConfigService.findFirstConfig(BaseConfigCodes.GETUI_HTTP_URL);
        if (appKeyConfig != null && masterSecretConfig != null && httpUrlConfig != null) {
            String httpUrl = httpUrlConfig.getValue();
            String timestamp = String.valueOf(System.currentTimeMillis());
            String appKey = appKeyConfig.getValue();
            String masterSecret = masterSecretConfig.getValue();
            String sign = SecureUtil.sha256(appKey + timestamp + masterSecret);
            Map<String, Object> param = new HashMap<>();
            param.put("appkey", appKey);
            param.put("timestamp", timestamp);
            param.put("sign", sign);
            String response = HttpRequest.post(httpUrl).body(JSONUtil.toJsonStr(param)).execute().body();
            GeTuiResult<GeTuiAuthResponse> result = GsonUtils.fromJson(response, new TypeToken<GeTuiResult<GeTuiAuthResponse>>() {
            }.getType());
            if (result.getCode() == GeTuiResult.SUCCESS) {
                log.info("getGeTuiToken response: {}", response);
                return result.getData();
            } else {
                log.info("getGeTuiToken error: {}", response);
                throw new ApiCoreException(Status.OPEN_SERVICE_FAILED);
            }
        } else {
            log.info("getGeTuiToken Configuration missing, please check");
            throw new ApiCoreException(Status.PARAMETER_ERROR);
        }
    }

    @Override
    public boolean pushSingleBatchCid(Set<Long> userIds, String title, String body, Long triggerId, Boolean buildName) {
        BaseConfig geTuiSwitch = baseConfigService.findFirstConfig(BaseConfigCodes.GETUI_ON_OFF);
        if (geTuiSwitch != null) {
            if (Constant.GETUI_ON.equals(geTuiSwitch.getValue())) {
                try {
                    String token = getTokenFromCache();
                    BaseConfig httpUrlConfig = baseConfigService.findFirstConfig(BaseConfigCodes.GETUI_PUSH_SINGLE_BATCH_ALIAS_HTTP_URL);
                    if (httpUrlConfig != null && StringUtils.isNotBlank(token)) {
                        String httpUrl = httpUrlConfig.getValue();
                        GeTuiPushBatchAliasReq<GeTuiPushBatchCidMsg> reqParam = new GeTuiPushBatchAliasReq<>();
                        reqParam.setIs_async(false);
                        List<GeTuiPushBatchCidMsg> msgList = buildGeTuiPushBatchMsg(userIds, title, body, buildName);
                        reqParam.setMsg_list(msgList);
                        log.info(JSONUtil.toJsonStr(reqParam));
                        String response = HttpRequest.post(httpUrl).header("token", token).body(JSONUtil.toJsonStr(reqParam)).execute().body();
                        GeTuiResult result = GsonUtils.fromJson(response, GeTuiResult.class);
                        if (GeTuiResult.SUCCESS == result.getCode()) {
                            log.info("pushSingleBatchAlias response: {}", response);
                            savePushMessageLog(msgList, title, response, Status.SUCCESS.getCode(), triggerId);
                            return true;
                        } else {
                            savePushMessageLog(msgList, title, response, Status.FAILED.getCode(), triggerId);
                            log.info("pushSingleBatchAlias error: {}", response);
                        }
                    } else {
                        log.info("pushSingleBatchAlias Configuration missing, please check");
                    }
                } catch (Exception e) {
                    log.error("pushSingleBatchCid Exception:", e);
                }
            } else {
                log.warn("pushSingleBatch config was off");
            }
        }
        return false;
    }

    private List<GeTuiPushBatchCidMsg> buildGeTuiPushBatchMsg(Set<Long> userIds, String title, String body, Boolean buildName) {
        List<GeTuiPushBatchCidMsg> msgList = new ArrayList<>();
        userIds.forEach(each -> {
            BaseLoginAccount account = loginAccountDao.findByUserDetailId(each);
            String finalBody = body;
            if (buildName && account != null) {
                finalBody = MessageFormat.format(body, account.getBaseUser().getRealName());
            }
            GeTuiNotification notification = GeTuiNotification.builder().
                    title(title).
                    body(finalBody).
                    click_type(GeTuiClickTypeEnum.STARTAPP.getValue()).
                    channel_level(GeTuiChannelLevelEnum.ALL.getValue()).
                    build();
            JSONObject strategy = JSONUtil.createObj().set("default", 3);
            if (account != null) {
                String clientId = account.getClientId();
                if (StringUtils.isNotBlank(clientId)) {
                    List<String> cid = new ArrayList<>();
                    cid.add(account.getClientId());
                    msgList.add(GeTuiPushBatchCidMsg.builder().
                            request_id(IdUtil.simpleUUID()).
                            audience(GeTuiAudience.builder().cid(cid).build()).
                            push_message(GeTuiPushBatchAliasPushMessage.builder().notification(notification).build()).
                            settings(GeTuiSettings.builder().ttl(24 * 3600 * 1000).strategy(strategy).build())
                            .build());
                } else {
                    log.warn("buildGeTuiPushBatchMsg error,user {} clientId is null", each);
                }
            } else {
                log.warn("Get baseLoginAccount error,user {} is null", each);
            }
        });
        return msgList;
    }


    /**
     * 保存推送消息的日志
     *
     * @param msgList    消息列表
     * @param title      消息标题
     * @param response   响应
     * @param pushStatus 发布状态
     * @return 消息日志集合
     */
    public void savePushMessageLog(List<GeTuiPushBatchCidMsg> msgList, String title,String response, Integer pushStatus, Long triggerId) {
        List<MessagePushLog> messagePushLogList = new ArrayList<>();
        for (GeTuiPushBatchCidMsg each : msgList) {
            MessagePushLog messagePushLog = new MessagePushLog();
            messagePushLog.setMsgList(JsonUtil.toJson(each));
            messagePushLog.setPushTitle(title);
            messagePushLog.setPushBody(each.getPush_message().getNotification().getBody());
            messagePushLog.setRequestId(each.getRequest_id());
            messagePushLog.setPushStatus(pushStatus);
            messagePushLog.setResponse(response);
            messagePushLog.setTriggerId(triggerId);
            messagePushLogList.add(messagePushLog);
        }
        // 2023/06/13 日志容量太大，取消保存
        //messagePushLogService.saveBatch(messagePushLogList);
    }
}
